#include <iostream>

#include <unistd.h>

#include <pthread.h>

pthread_key_t p_key;
#ifdef __GNUC__
__thread int _ta = 10;
#endif

struct Test
{
    Test(int a = 0)
        : _a(a)
    {}

    ~Test()
    {
        std::cout << "~Test" << std::endl;
    }
    int _a = 0;
};

void fun()
{
    Test* p = (Test*)pthread_getspecific(p_key);
    printf("fun p->_a = %d\n", p->_a);
    p->_a += 2;
}

void* thread_run(void* args)
{
    _ta += 10;
    printf("%p pthread var_ta: %d\n", pthread_self(), _ta);
    pthread_setspecific(p_key, args);
    int a = 100;
    pthread_setspecific(p_key, (const void*)&a);
    Test* p = (Test*)pthread_getspecific(p_key);
    p->_a += 1;
    fun();
    printf("thread_run p->_a = %d\n", p->_a);

    return NULL;
}

void* thread_test(void* args)
{
    pthread_setspecific(p_key, args);
    int* pa = (int*)pthread_getspecific(p_key);
    *pa += 10;
    usleep(100000);
    std::cout << (*pa) << std::endl;
    return NULL;
}

int main()
{
    pthread_key_create(&p_key, NULL);

    Test a = 0, b = 0;

    pthread_t ta, tb;
    pthread_create(&ta, NULL, thread_run, &a);
    pthread_create(&tb, NULL, thread_run, &b);

    pthread_join(ta, NULL);
    pthread_join(tb, NULL);

    pthread_key_delete(p_key);

    pthread_key_create(&p_key, NULL);
    int aa = 0;
    pthread_create(&ta, NULL, thread_test, &aa);
    pthread_create(&tb, NULL, thread_test, &aa);
    
    pthread_join(ta, NULL);
    pthread_join(tb, NULL);
    std::cout << aa << std::endl;
    
    return 0;
}
